# -*- coding: utf-8 -*-
import os
os.environ['KERAS_BACKEND']='tensorflow'


import keras
from keras import optimizers
from keras.layers import Input, AveragePooling2D, GlobalMaxPool2D
from keras.layers import MaxPool2D, Dropout, BatchNormalization, GlobalAvgPool2D, LeakyReLU, PReLU, ELU, \
    ThresholdedReLU, ReLU
from keras.layers.convolutional import Conv2D, SeparableConv2D
from keras.layers.core import Activation, Lambda
from keras.layers.core import Dense
from keras.models import Model
from tensorflow.python.keras.utils import plot_model

from keras.layers import Input, Dense
from keras.layers import LSTM
from keras.models import Model
from keras.layers import Dense, Dropout, Reshape, Permute
from keras.layers.convolutional import Convolution2D
from keras.layers.convolutional import MaxPooling2D, ZeroPadding2D
from keras.layers.normalization import BatchNormalization
from keras.layers.recurrent import GRU
from keras.optimizers import SGD, rmsprop
from keras.utils.np_utils import to_categorical
from keras.callbacks import EarlyStopping, ModelCheckpoint, TensorBoard
import matplotlib.pyplot as plt
# from keras.utils.visualize_util import plot
from keras.utils.vis_utils import plot_model
from keras import regularizers
from keras.layers import LeakyReLU

def CNN(input_shape=(60, 65, 1), nclass=10):
    """
    build a simple cnn models using keras with TensorFlow backend.
    :param input_shape: input shape of network, default as (60,65,1)
    :param nclass: numbers of class(output shape of network), default as 10
    :return: cnn models
    """
    input_ = Input(shape=input_shape)
    print(input_)

    # 尝试
    # Conv1
    x = Conv2D(128, kernel_size=(3, 3), strides=(1, 1), padding='same')(input_)
    # x = BatchNormalization()(x)
    x = LeakyReLU(alpha=0.05)(x)
    # x = Activation('relu')(x)
    x = Dropout(0.5)(x)
    x = MaxPool2D(pool_size=(2, 2), strides=(2, 2))(x)



    x = Conv2D(256, kernel_size=(3, 3), strides=(1, 1), padding='same')(x)
    # x = BatchNormalization()(x)
    x = LeakyReLU(alpha=0.05)(x)
    # x = Activation('relu')(x)
    x = Dropout(0.5)(x)
    x = MaxPool2D(pool_size=(2, 2), strides=(2, 2))(x)

    x = Conv2D(256, kernel_size=(3, 3), strides=(1, 1), padding='same')(x)
    # x = BatchNormalization()(x)
    # x = Activation('relu')(x)
    x = LeakyReLU(alpha=0.05)(x)
    x = Dropout(0.5)(x)
    x = MaxPool2D(pool_size=(2, 2), strides=(2, 2))(x)

    x = Conv2D(512, kernel_size=(3, 3), strides=(1, 1), padding='same')(x)
    # x = BatchNormalization()(x)
    # x = Activation('relu')(x)
    x = LeakyReLU(alpha=0.05)(x)
    x = Dropout(0.5)(x)




    # GAP
    x = GlobalAvgPool2D()(x)

    # x = GlobalMaxPool2D()(x)
    # print("x=",x)
    # x = Reshape((60, 65))(x)
#################################################################################################################
    # reshape1 = Reshape((56, 512))(x)
    # lstm1 = LSTM(input_shape=(56, 512), output_dim=30, activation='tanh', return_sequences=False)(reshape1)
    # x = Dropout(0.5)(lstm1)

###################################################################################################################

    # # Dense_1
    x = Dense(512)(x)
    x = LeakyReLU(alpha=0.05)(x)
    x = Dropout(0.5)(x)
    # # x = Dense(4096)(x)
    # x = LeakyReLU(alpha=0.05)(x)
    # # x = PReLU(alpha_initializer='zeros', alpha_regularizer=None, alpha_constraint=None, shared_axes=None)(x)
    # # x = ELU(alpha=1.0)(x)
    # # x = ThresholdedReLU(theta=1.0)(x)
    # # x = ReLU(max_value=None, negative_slope=0.0, threshold=0.0)(x)
    # x = Dropout(0.5)(x)

    # x = Dense(512)(x)
    # x = LeakyReLU(alpha=0.05)(x)
    # x = Dropout(0.5)(x)

    # Dense_2
    output_ = Dense(nclass, activation='softmax')(x)
    # output_ = Dense.max(nclass, activation='softmax')(x)

    model = Model(inputs=input_, outputs=output_)
    # 输出模型的参数信息
    model.summary()
    # 配置模型训练过程
    # sgd = optimizers.sgd(lr=0.01, momentum=0.9, nesterov=True)  # 优化器为SGD
    # models.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy'])  # 交叉熵为cross entropy

    # adam = optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0)
    # models.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])

    # 最好 lr = 0.001
    # adam = optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0)
    adam = optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0)
    model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])


    return model


if __name__ == '__main__':
    model = CNN()
    # plot_model(model, './image/cnn1.png')  # 保存模型图
